# -*- coding: utf-8 -*-
# @Author: bao
# @Date:   2017-02-17 11:20:24
# @Last Modified by:   bao
# @Last Modified time: 2017-05-14 14:45:03

from gen_topo import *
from gen_topo_fully import *
from datetime import datetime

class gen_topo_ovs(gen_topo_fully):
	"""
	blocking circuit switch
	"""
	def __init__(self):
		gen_topo_fully.__init__(self)
	
	def _transform(self, wl_graph, tf_graph, degree, row_size, base_len):
		'''
		Generate new topology based on multi max_weight_matching (directed bipartite graph)
		node (bp_src, bipartite=0, degree=0)
		node (bp_dst, bipartite=0, degree=0)
		edge (src, dst, 'weight')
		'''
		print "_transform_ovs"
		remain_edges = []
		temp_graph = tf_graph.copy()
		while temp_graph.edges():
			match = nx.max_weight_matching(temp_graph, maxcardinality=False)
			#print match
			for src in match:
				dst = match[src]
				if src <= base_len:
					#print src, dst, temp_graph[src][dst]['weight']
					(src_axis_x, src_axis_y) = get_cd(src, row_size)
					(dst_axis_x, dst_axis_y) = get_cd(dst-base_len, row_size)
					(Is_same_axis, cp_x, cp_y) = get_cp((src_axis_x, src_axis_y), (dst_axis_x, dst_axis_y), row_size, base_len)
					
					traffic_weight = get_weight(temp_graph[src][dst]['weight'])

					if Is_same_axis:
						max_degree = max(wl_graph.node[src]['degree'], wl_graph.node[dst]['degree'])
						if max_degree < degree:
							wl_max = degree - max_degree
							wl_num = min(traffic_weight, wl_max)
							wl_graph.node[src]['degree'] += wl_num
							wl_graph.node[dst]['degree'] += wl_num
							if (src, dst) not in wl_graph.edges():
								wl_graph.add_edge(src, dst, weight=wl_num)
							else:
								wl_graph.edge[src][dst]['weight'] += wl_num
						else:
							remain_edges.append((src, dst))
					else:
						max_degree_x = max(wl_graph.node[src]['degree'], wl_graph.node[dst]['degree'], wl_graph.node[cp_x]['degree'], wl_graph.node[cp_x-base_len]['degree']) # Indegree and Outdegree
						max_degree_y = max(wl_graph.node[src]['degree'], wl_graph.node[dst]['degree'], wl_graph.node[cp_y]['degree'], wl_graph.node[cp_y-base_len]['degree']) # Indegree and Outdegree
						if max_degree_x > max_degree_y:
							cp = cp_y
							max_degree = max_degree_y
						else:
							cp = cp_x
							max_degree = max_degree_x

						if max_degree < degree:
							wl_max = degree - max_degree
							wl_num = min(traffic_weight, wl_max)

							if (src, cp) not in wl_graph.edges():
								wl_graph.add_edge(src, cp, weight=wl_num)
							else:
								wl_graph.edge[src][cp]['weight'] += wl_num

							if (cp-base_len, dst) not in wl_graph.edges():
								wl_graph.add_edge(cp-base_len, dst, weight=wl_num)
							else:
								wl_graph.edge[cp-base_len][dst]['weight'] += wl_num

							wl_graph.node[src]['degree'] += wl_num
							wl_graph.node[dst]['degree'] +=  wl_num
							wl_graph.node[cp]['degree'] += wl_num
							wl_graph.node[cp-base_len]['degree'] += wl_num
						else:
							remain_edges.append((src, dst))
					temp_graph.remove_edge(src, dst)